{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cb354baf",
   "metadata": {},
   "source": [
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/langchain-ai/langchain-academy/blob/main/module-1/router.ipynb) [![Open in LangChain Academy](https://cdn.prod.website-files.com/65b8cd72835ceeacd4449a53/66e9eba12c7b7688aa3dbb5e_LCA-badge-green.svg)](https://academy.langchain.com/courses/take/intro-to-langgraph/lessons/58239412-lesson-5-router)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ce6fff79-25b5-4884-8aaa-e3ebb7ddd549",
   "metadata": {},
   "source": [
    "# Router\n",
    "\n",
    "## Review\n",
    "\n",
    "We built a graph that uses `messages` as state and a chat model with bound tools.\n",
    "\n",
    "We saw that the graph can:\n",
    "\n",
    "* Return a tool call\n",
    "* Return a natural language response\n",
    "\n",
    "## Goals\n",
    "\n",
    "We can think of this as a router, where the chat model routes between a direct response or a tool call based upon the user input.\n",
    "\n",
    "This is a simple example of an agent, where the LLM is directing the control flow either by calling a tool or just responding directly. \n",
    "\n",
    "![Screenshot 2024-08-21 at 9.24.09 AM.png](https://cdn.prod.website-files.com/65b8cd72835ceeacd4449a53/66dbac6543c3d4df239a4ed1_router1.png)\n",
    "\n",
    "Let's extend our graph to work with either output! \n",
    "\n",
    "For this, we can use two ideas:\n",
    "\n",
    "(1) Add a node that will call our tool.\n",
    "\n",
    "(2) Add a conditional edge that will look at the chat model output, and route to our tool calling node or simply end if no tool call is performed. \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ebb4fc6e-7c85-4fc8-a4a9-0c7a527c4e5b",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture --no-stderr\n",
    "%pip install --quiet -U langchain_openai langchain_core langgraph langgraph-prebuilt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "885e92d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os, getpass\n",
    "\n",
    "def _set_env(var: str):\n",
    "    if not os.environ.get(var):\n",
    "        os.environ[var] = getpass.getpass(f\"{var}: \")\n",
    "\n",
    "_set_env(\"OPENAI_API_KEY\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e3ba4df4-3045-49b1-9299-ced1fce14d24",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "def multiply(a: int, b: int) -> int:\n",
    "    \"\"\"Multiply a and b.\n",
    "\n",
    "    Args:\n",
    "        a: first int\n",
    "        b: second int\n",
    "    \"\"\"\n",
    "    return a * b\n",
    "\n",
    "llm = ChatOpenAI(model=\"gpt-4o\")\n",
    "llm_with_tools = llm.bind_tools([multiply])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c77555a2",
   "metadata": {},
   "source": [
    " We use the [built-in `ToolNode`](https://langchain-ai.github.io/langgraph/reference/prebuilt/?h=tools+condition#toolnode) and simply pass a list of our tools to initialize it. \n",
    " \n",
    " We use the [built-in `tools_condition`](https://langchain-ai.github.io/langgraph/reference/prebuilt/?h=tools+condition#tools_condition) as our conditional edge."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9a6fde4e-cceb-4426-b770-97ee4b41e9da",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "from langgraph.graph import MessagesState\n",
    "from langgraph.prebuilt import ToolNode\n",
    "from langgraph.prebuilt import tools_condition\n",
    "\n",
    "# Node\n",
    "def tool_calling_llm(state: MessagesState):\n",
    "    return {\"messages\": [llm_with_tools.invoke(state[\"messages\"])]}\n",
    "\n",
    "# Build graph\n",
    "builder = StateGraph(MessagesState)\n",
    "builder.add_node(\"tool_calling_llm\", tool_calling_llm)\n",
    "builder.add_node(\"tools\", ToolNode([multiply]))\n",
    "builder.add_edge(START, \"tool_calling_llm\")\n",
    "builder.add_conditional_edges(\n",
    "    \"tool_calling_llm\",\n",
    "    # If the latest message (result) from assistant is a tool call -> tools_condition routes to tools\n",
    "    # If the latest message (result) from assistant is a not a tool call -> tools_condition routes to END\n",
    "    tools_condition,\n",
    ")\n",
    "builder.add_edge(\"tools\", END)\n",
    "graph = builder.compile()\n",
    "\n",
    "# View\n",
    "display(Image(graph.get_graph().draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "11b608c5-0c15-4fb7-aa24-80ce5774fb85",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "\n",
      "Hello world.\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "Hello! How can I assist you today?\n"
     ]
    }
   ],
   "source": [
    "from langchain_core.messages import HumanMessage\n",
    "messages = [HumanMessage(content=\"Hello, what is 2 multiplied by 2?\")]\n",
    "messages = graph.invoke({\"messages\": messages})\n",
    "for m in messages['messages']:\n",
    "    m.pretty_print()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "34708377-16b6-4474-9e23-71890c1fb36e",
   "metadata": {},
   "source": [
    "Now, we can see that the graph runs the tool!\n",
    "\n",
    "It responds with a `ToolMessage`. \n",
    "\n",
    "## LangGraph Studio\n",
    "\n",
    "**⚠️ DISCLAIMER**\n",
    "\n",
    "Since the filming of these videos, we've updated Studio so that it can be run locally and opened in your browser. This is now the preferred way to run Studio (rather than using the Desktop App as shown in the video). See documentation [here](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/#local-development-server) on the local development server and [here](https://langchain-ai.github.io/langgraph/how-tos/local-studio/#run-the-development-server). To start the local development server, run the following command in your terminal in the `/studio` directory in this module:\n",
    "\n",
    "```\n",
    "langgraph dev\n",
    "```\n",
    "\n",
    "You should see the following output:\n",
    "```\n",
    "- 🚀 API: http://127.0.0.1:2024\n",
    "- 🎨 Studio UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024\n",
    "- 📚 API Docs: http://127.0.0.1:2024/docs\n",
    "```\n",
    "\n",
    "Open your browser and navigate to the Studio UI: `https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024`.\n",
    "Load the `router` in Studio, which uses `module-1/studio/router.py` set in `module-1/studio/langgraph.json`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "43782c33-0f41-47f2-ae38-ddb2cd4ba6f8",
   "metadata": {},
   "outputs": [],
   "source": [
    "if 'google.colab' in str(get_ipython()):\n",
    "    raise Exception(\"Unfortunately LangGraph Studio is currently not supported on Google Colab\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94928b21",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "academy",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
